← All Articles

[BAEKJOON] 3745. 오름세

Posted on

문제 :

주식투자를 좋아하는 정인이는 주가의 오름세를 살펴보려고 한다.

정인이는 n일 동안 매일 주가를 적어놓았고, 여기서 오름세를 찾아보려고 한다.

n일 동안의 주가를 p1, p2, …, pn이라고 했을 때, 오름세란 부분수열 pi1 < pi2 < … < pik (i1 < i2 < … ik)을 말한다.

n일 동안 주가가 주어졌을 때, 가장 긴 오름세를 찾는 프로그램을 작성하시오.


입력 :

입력은 여러개의 테스트 케이스로 이루어져 있다. 각 테스트 케이스의 첫째 줄에는 주가를 관찰한 날의 수 N (N ≤ 100000)이 주어진다. 둘째 줄에는 관찰한 주가가 첫 날부터 순서대로 주어진다. 주가는 한 개 이상의 공백으로 구분되어 있으며, 그 외의 위치에서도 자유롭게 나올 수 있다. 주가는 100,000보다 작거나 같은 자연수이다.


출력 :

각 테스트 케이스에 대해서 입력으로 주어진 주가의 가장 긴 오름세의 길이를 출력한다.




풀이 :

문제는 LIS (Longest Increasing Subsequence) 증가하는 최장 부분 수열을 구현해봤다면 쉽게 해결할 수 있는 문제였다.

하지만 나 역시 LIS 문제를 푼지 오래 지나서인지 기억이 가물가물했다.

그래서 이참에 LIS 문제 풀이 방식 2가지를 정리하고 문제를 해결했다.

[ LIS ]

  • LIS의 경우 두 가지 방식으로 풀 수 있다. DP와 이분 탐색 방법으로 풀 수 있는데(세그먼트 트리 방법도 있긴 하지만 오늘 정리는 본 두가지 방식만 정리해보았다.) DP 방식의 경우 O(n^2) 시간 복잡도를 가져서 본 문제에서는 시간 내에 해결할 수 없다. 따라서 이분 탐색을 활용해 문제를 해결해야 한다.
  • 이분 탐색을 사용하는 방식은 수열의 앞에서부터 벡터에 하나씩 집어 넣는 식으로 문제를 해결하는데, 이 과정에서 벡터의 가장 마지막 원소보다 큰 숫자가 들어올 경우 벡터 끝에 삽입해주고 그렇지 않을 경우에는 lower bound 위치의 인덱스에 해당 숫자를 교체해준다(삽입이 아니고 교체임!)
  • Lower bound : 오름차순 정렬된 배열에서 해당 숫자보다 크거나 같은(이상) 숫자 위치를 말함
  • Upper bound : 오름차순 정렬된 배열에서 해당 숫자보다 큰(초과) 숫자 위치를 말함

본 문제는 전형적인 LIS 문제이기 때문에 위처럼 이분 탐색의 LIS 방식을 사용하면 문제를 해결할 수 있다!




코드 :

코드 보기/접기
#include <iostream>
#include <vector>

using namespace std;
vector<int> ansvec;
int n;

void binarySearch(int input, int left, int right) {
    if (!ansvec.size() || ansvec[ansvec.size() - 1] < input) {
        ansvec.push_back(input);
        return;
    }
    if (left >= right) {
        if (ansvec[left] > input) ansvec[left] = input;
        return;
    }

    int mid = (left + right) / 2;
    if (ansvec[mid] >= input) binarySearch(input, left, mid);
    else binarySearch(input, mid + 1, right);
}

int main() {
    int input;

    while (cin >> n) {
        ansvec.clear();
        for (int i = 0; i < n; i++) {
            cin >> input;
            binarySearch(input, 0, ansvec.size() - 1);
        }
        cout << ansvec.size() << '\n';
    }
    return 0;
}



AlgorithmalgorithmbaekjoonC++